package syM

import (
	"errors"
	"fmt"
	"db2s/global"
	"db2s/go-log/log"
	"db2s/outPut"
	"reflect"
	"sync/atomic"
)

func SendMsgExecSumFunc(param any) global.EFunc {
	return global.EFunc{
		FuncName: func(event string,s any) (r any) {
			var point []any
			var val int64
			switch s.(type) {
			case []any:
				for k, v := range s.([]any) {
					switch k {
					case 0:
						switch reflect.TypeOf(v).String() {
						case "interface {}", "*int64":
							point = append(point, v)
						case "[]interface {}":
							for _, q := range v.([]any) {
								point = append(point, q)
							}
						}
					case 1:
						val = v.(int64)
					}
				}
			}
			for _, v := range point {
				switch v.(type) {
				case *int64:
					atomic.AddInt64(v.(*int64), val)
				}
			}
			return
		},
		Params: param,
	}
}
func structXlsWriteTerminalData(plan *SchedulePlan2, logSeq int64) error {
	var (
		event = "[structXlsWriteTerminalData]"
		vlog  string
	)
	vlog = fmt.Sprintf("(%d) %v Start writing the execution results of table %v.%v into xls...", logSeq, event, plan.Object.Schema, plan.Object.Table)
	log.MainLog().Debug(vlog)
	if e := atomic.LoadInt64(plan.Status.ErrEnd); e < 0 {
		plan.TPod.Result = "error"
		vlog = fmt.Sprintf("(%d) %v There is an error in table %v.%v Modify the result status information to error.", logSeq, event, plan.Object.Schema, plan.Object.Table)
		log.MainLog().Warn(vlog)
	}
	plan.TPod.Seq = plan.Object.TaskSeq
	//sheet
	if *plan.TPod.Status == -1 || *plan.TPod.Status == -2 {
		plan.TPod.Result = "abnormal"
	}
	newTer.Write(plan.TPod)
	plan.XlsTerminal.Data = *plan.TPod
	newCell.Write(plan.XlsTerminal)
	vlog = fmt.Sprintf("(%d) %v The execution result of table %v.%v is sent successfully.", logSeq, event, plan.Object.Schema, plan.Object.Table)
	log.MainLog().Debug(vlog)
	return nil
}
func objectXlsWriteTerminalData(plan *SchedulePlan2, logSeq int64) (err error) {
	var (
		event = "[structXlsWriteTerminalData]"
		vlog  string
	)
	vlog = fmt.Sprintf("(%d) %v Start writing the execution results of table %v.%v into xls...", logSeq, event, plan.Object.Schema, plan.Object.Table)
	log.MainLog().Debug(vlog)
	if e := atomic.LoadInt64(plan.Status.ErrEnd); e < 0 {
		plan.TPod.Result = "error"
		vlog = fmt.Sprintf("(%d) %v There is an error in table %v.%v Modify the result status information to error.", logSeq, event, plan.Object.Schema, plan.Object.Table)
		log.MainLog().Warn(vlog)
	}
	plan.TPod.Seq = plan.Object.TaskSeq
	//sheet
	if *plan.TPod.Status == -1 || *plan.TPod.Status == -2 {
		plan.TPod.Result = "abnormal"
	}
	newTer.Write(plan.TPod)
	plan.XlsTerminal.Data = *plan.TPod
	newCell.Write(plan.XlsTerminal)
	vlog = fmt.Sprintf("(%d) %v The execution result of table %v.%v is sent successfully.", logSeq, event, plan.Object.Schema, plan.Object.Table)
	log.MainLog().Debug(vlog)
	return
}
func getXlsWriteTerminalFunc() map[string]reflect.Value {
	return map[string]reflect.Value{
		"struct": reflect.ValueOf(structXlsWriteTerminalData),
		"object": reflect.ValueOf(objectXlsWriteTerminalData),
	}
}
func xlsWriterTerminalData(plan *SchedulePlan2, logSeq int64) (err error) {
	if funcName, ok := getXlsWriteTerminalFunc()[GlobalPConfigs.rules.CheckMode]; ok {
		if funcName.Kind() == reflect.Func {
			args := []reflect.Value{
				reflect.ValueOf(plan),
				reflect.ValueOf(logSeq),
			}
			s := funcName.Call(args)[0].Interface()
			if s != nil {
				err = errors.New(fmt.Sprintf("%v", s))
			}
			return
		}
	}
	return
}
func singleTableFinishXlsWriteAction(plan *SchedulePlan2) (err error) {
	var event = "[singleTableFinishXlsWriteAction]"
	log.MainLog().Debug(fmt.Sprintf("(%v) %v begin exec finish object xls write of table %v.%v .", plan.Object.ObjectLogSeq, event, plan.Object.Schema, plan.Object.Table))
	if err = xlsWriterTerminalData(plan, plan.Object.ObjectLogSeq); err != nil {
		log.MainLog().Warn(fmt.Sprintf("(%v) %v exec finish object xls write fail of table %v.%v. error is {%v}", plan.Object.ObjectLogSeq, event, plan.Object.Schema, plan.Object.Table, err))
		return
	}
	log.MainLog().Info(fmt.Sprintf("(%v) %v exec finish object xls write successful of table %v.%v.", plan.Object.ObjectLogSeq, event, plan.Object.Schema, plan.Object.Table))
	return
}

func closeDataFile(plan *SchedulePlan2) {
	var fileGarth = map[string]outPut.FileOperations{plan.fixFile.AlterFileName: plan.fixFile.AlterFilePoint, plan.fixFile.CreateFileName: plan.fixFile.CreateFilePoint}
	if getDataFixFileSingleFay() {
		return
	}
	for k, v := range fileGarth {
		if v != nil {
			if err := v.Close(); err != nil {
				return
			}
		}
		if err := emptyFile(k); err != nil {
			log.MainLog().Warn(fmt.Sprintf(""))
		}
	}
}
func mqStatusMonitorAbnormalQuit(event string,i any) (r any) {
	var plan *SchedulePlan2
	switch i.(type) {
	case *SchedulePlan2:
		plan = i.(*SchedulePlan2)
	default:
		return
	}
	_ = singleTableFinishXlsWriteAction(plan)
	closeDataFile(plan)
	PlanContext.TaskBarSubsStatusSwap(plan.subTaskInfo, "error")
	return
}
func mqStatusMonitorNormalQuit(event string,i any) (r any) {
	var plan *SchedulePlan2
	switch i.(type) {
	case *SchedulePlan2:
		plan = i.(*SchedulePlan2)
	default:
		return
	}
	event = "[mqStatusMonitorNormalQuit]"
	log.MainLog().Debug(fmt.Sprintf("(%d) %v It is detected that the message queue production quantity and consumption quantity in table %v.%v are equal.", plan.Object.ObjectLogSeq, event, plan.Object.Schema, plan.Object.Table))
	_ = singleTableFinishXlsWriteAction(plan)
	closeDataFile(plan)
	PlanContext.TaskBarSubsStatusSwap(plan.subTaskInfo, "finish")
	log.MainLog().Info(fmt.Sprintf("(%v) %v Table %v.%v data migration is completed.", plan.Object.ObjectLogSeq, event, plan.Object.Schema, plan.Object.Table))
	return
}

func getMsgSendData(plan *SchedulePlan2, si map[string]any) (res map[string]any) {
	res = map[string]any{
		"plan":    plan,
		"check":   getCheckMod(),
		"subTask": plan.subTaskInfo,
		"err":     plan.Status.ErrEnd,
		"outFay":  GlobalPConfigs.result.Teletypewriter,
	}
	for k, v := range si {
		res[k] = v
	}
	return
}
